package org.kele.sc2020.proivder.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.kele.sc2020.proivder.service.GroupTaskService;
import org.kele.sc2020.proivder.service.InstanceService;
import org.kele.sc2020.proivder.service.ShardGroupTaskEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ShardGroupTaskEngineImpl implements ShardGroupTaskEngine {

    @Autowired
    private InstanceService instanceService;

    @Autowired
    private GroupTaskService groupTaskService;

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public String handleGroup(Integer i) {

        //虚拟一个由查询处理来的 待处理任务集合
        List<Integer> task = Arrays.asList(1, 3, 2, 4, 5, 1, 54, 2, 23, 13, 35, 100, 24);
        List<ServiceInstance> availableInstaces = instanceService.findAvailableInstaces();
        List<List<Integer>> lists = groupTaskService.groupIntoList(task, availableInstaces.size());
        List<CompletableFuture<String>> waitList = new ArrayList<>(lists.size());
        for (int c = 0; c < lists.size(); c++) {
            List<Integer> group = lists.get(c);
            if (c == lists.size() - 1) { //最后一组总是留给当前实例处理; 如果只有一组,则默认当前实例处理;
                waitList.add(CompletableFuture.supplyAsync(() -> handelSubGroup(group)));
            } else {
                ServiceInstance instance = availableInstaces.get(c);
                CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> sendToSubGroup(group, instance));
                waitList.add(stringCompletableFuture);
            }
        }
        CompletableFuture.allOf(waitList.toArray(new CompletableFuture[0])).join();
        return waitList.stream().map(e -> e.getNow("no ele")).collect(Collectors.joining("&"));

    }

    private String sendToSubGroup(List<Integer> list, ServiceInstance instance) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<List<Integer>> requestEntity = new HttpEntity<>(list, headers);
        String url = CharSequenceUtil.format("http://{}:{}/shard/group-task", instance.getHost(), instance.getPort());
        return restTemplate.postForObject(url, requestEntity, String.class);
    }

    @Override
    public String handelSubGroup(List<Integer> ids) {
        return StringUtils.join(ids, "=group by instace=");
    }
}
